/*
 * Copyright (c) 2005 - 2008 Christoph Wimmer
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.rms.*;

public class QRMidlet extends MIDlet implements CommandListener {
	// UI Elements
	private Display display;
	private Form resultForm;
	private Form waitForm;
        private Form settingsForm;
	private Command exitCommand;
	private Command cameraCommand;
	private Command cancelCommand;
	private Command captureCommand;
	private Command callCommand;
	private Command openCommand;
	private Command smsCommand;
	private Command settingsCommand;
	private Command saveSettingsCommand;
	private StringItem resultStringItem;
	private ChoiceGroup resolutionChoiceGroup;
        private Gauge waitGauge;
	private Player player;
	private VideoControl videoControl;
        private Canvas canvas;
	// Settings & initialization with default values
        private int captureProfile = 0;
	// Settings record store stuff
	private RecordStore db = null;
        // Midlet started or resumed, initiallize to not started
        private boolean started = false;
        // Midlet name
        private String midletName = "QRMidlet";

	public QRMidlet() {
            // nothing to do here
	}

	public void startApp() {
            // initialize one-time resources on startup
            if (started == false) {
                started = true;
                // get display handle
		display = Display.getDisplay(this);
		// load settings
		loadSettings();
                
                // initialize commands
		exitCommand = new Command("Exit", Command.EXIT, 1);
		cameraCommand = new Command("Camera", Command.SCREEN, 1);
		cancelCommand = new Command("Cancel", Command.CANCEL, 2);
		captureCommand = new Command("Capture", Command.SCREEN, 1);
		settingsCommand = new Command("Settings", Command.SCREEN, 2);
		saveSettingsCommand = new Command("Save", Command.OK, 1);
		callCommand = new Command("Call", Command.ITEM, 2);
		openCommand = new Command("Open", Command.ITEM, 2);
                smsCommand = new Command("Send SMS", Command.ITEM, 2);
		// initialize settings form
		settingsForm = new Form(midletName);
		String[] resolutions = {"Automatic", "160x120", "320x240", "640x480"};
		resolutionChoiceGroup = new ChoiceGroup("Resolution: ", Choice.EXCLUSIVE, resolutions, null);
		settingsForm.append(resolutionChoiceGroup);
		settingsForm.addCommand(saveSettingsCommand);
		settingsForm.addCommand(cancelCommand);
		settingsForm.setCommandListener(this);
		// initialize waiting form
                waitForm = new Form(midletName);
                waitGauge = new Gauge("Processing, please wait...", false, Gauge.INDEFINITE, Gauge.CONTINUOUS_RUNNING);
		waitForm.append(waitGauge);
                
                // initialize player, videocontrol, canvas
                try {
                    // create player and realize it
                    player = createPlayer();
                    player.realize();
                    // get videocontrol
                    videoControl = (VideoControl)player.getControl("VideoControl");
                    // initialize camera canvas
                    canvas = new CameraCanvas(this);
                    // initialize video control
                    videoControl.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, canvas);
                    videoControl.setDisplayFullScreen(true);
                    videoControl.setVisible(true);
                } catch (Exception e) {
                    handleException(e);
                }
                canvas.addCommand(exitCommand);
                canvas.addCommand(captureCommand);
                canvas.addCommand(settingsCommand);
                canvas.setCommandListener(this);
                showCamera();
            } else {
                // when resuming from paused state
		if (display.getCurrent() == canvas) {
                    try {
                        player.start();
                    } catch (Exception e) {
                        handleException(e);
                    }
		}
		display.setCurrent(display.getCurrent());
            }
	}

	public void pauseApp() {
            if (player != null) {
                try {
                    player.stop();
                } catch (Exception e) {
                    handleException(e);
                }
            }
        }

	public void destroyApp(boolean unconditional) {
            if (player != null) {
                videoControl = null;
                try {
                    player.stop();
                } catch (Exception e) {
                    handleException(e);
                }
                player.deallocate();
                player.close();
                player = null;
            }
        }

	public void commandAction(Command c, Displayable s) {
		if (c.getCommandType() == Command.EXIT) {
			destroyApp(true);
			notifyDestroyed();
		} else if (c == cameraCommand) {
			showCamera();
		} else if (c == cancelCommand) {
			showCamera();
		} else if (c == captureCommand) {
			capture();
		} else if (c == callCommand) {
			dispatchPlatformRequest();
		} else if (c == openCommand) {
			dispatchPlatformRequest();
		} else if (c == smsCommand) {
			dispatchPlatformRequest();
		} else if (c == settingsCommand) {
			closeCamera();
			showSettings();
		} else if (c == saveSettingsCommand) {
			saveSettings();
			showCamera();
		}
	}
        
        private Player createPlayer() {
            Player mPlayer = null;
            // try capture://image first for series 40 phones
            try {
                mPlayer = Manager.createPlayer("capture://image");
            } catch (Exception e) {
                handleException(e);
            } catch (Error e) {
                // continue
            }
            // if capture://image failed, try capture://video
            if (mPlayer == null) {
                try {
                    mPlayer = Manager.createPlayer("capture://video");
                } catch (Exception e) {
                    handleException(e);
                }
            }
            return mPlayer;
        }

	private void showCamera() {
		try {
			display.setCurrent(canvas);
			player.start();
		} catch (Exception e) {
			handleException(e);
		}
	}
	
	public void closeCamera() {
                try {
                    player.stop();
                } catch (Exception e) {
                    handleException(e);
                }
	}

	public void capture() {
		try {
			// display waiting screen during decoding
			display.setCurrent(waitForm);
			// capture and decode image in its own thread
			DecodeThread decodeThread = new DecodeThread(this);
			decodeThread.start();
		} catch (Exception me) {
			handleException(me);
		}
	}
	
	public void showResult(String result) {
		// initialize result form
		resultForm = new Form(midletName);
		resultStringItem = new StringItem("Result: ", result);
		resultForm.addCommand(exitCommand);
		resultForm.addCommand(cameraCommand);
		// do some simple result parsing
		if (result.startsWith("tel:")) {
			resultForm.addCommand(callCommand);
		} else if (result.startsWith("http://")) {
			resultForm.addCommand(openCommand);
		} else if (result.startsWith("sms:")) {
			resultForm.addCommand(smsCommand);
		}
		resultForm.append(resultStringItem);
		resultForm.setCommandListener(this);
		// display result form.
		display.setCurrent(resultForm);
	}
        
	private void dispatchPlatformRequest() {
		try {
			platformRequest(resultStringItem.getText());
		} catch (ConnectionNotFoundException cnfe) {
			handleException(cnfe);
		}
		destroyApp(true);
		notifyDestroyed();
	}

        public String getCaptureSettings() {
            String captureString = null;
            if (captureProfile == 1) {
                captureString = "encoding=jpeg&width=160&height=120";
            } else if (captureProfile == 2) {
                captureString = "encoding=jpeg&width=320&height=240";
            } else if (captureProfile == 3) {
                captureString = "encoding=jpeg&width=640&height=480";
            } else {
                captureString = null;
            }
            return captureString;
        }
        
	private void loadSettings() {
		try {
			db = RecordStore.openRecordStore("settings", true);
			if (db.getNumRecords() > 0) {
				byte[] record = db.getRecord(1);
				String cp = new String(record);
                                captureProfile = Integer.parseInt(cp);
			} else {
				captureProfile = 0;
			}
			db.closeRecordStore();
		} catch (RecordStoreException rse) {
			handleException(rse);
		}
	}

	private void saveSettings() {
		int choice = resolutionChoiceGroup.getSelectedIndex();
		boolean settingsChanged = false;
		if ((choice == 0) && (captureProfile != 0)) {
			captureProfile = 0;
			settingsChanged = true;
		} else if ((choice == 1) && (captureProfile != 1)) {
			captureProfile = 1;
			settingsChanged = true;
		} else if ((choice == 2) && (captureProfile != 2)) {
			captureProfile = 2;
			settingsChanged = true;
		} else if ((choice == 3) && (captureProfile != 3)) {
			captureProfile = 3;
			settingsChanged = true;
		}
		if (settingsChanged == true) {
			try {
				db = RecordStore.openRecordStore("settings", true);
                                String cp = Integer.toString(captureProfile);
				byte[] record = (cp).getBytes();
				if (db.getNumRecords() == 0) {
					db.addRecord(record, 0, record.length);
				} else {
					db.setRecord(1, record, 0, record.length);
				}
				db.closeRecordStore();
			} catch (RecordStoreException rse) {
				handleException(rse);
			}
		}
	}
	
	private void showSettings() {
		resolutionChoiceGroup.setSelectedIndex(captureProfile, true);
		display.setCurrent(settingsForm);
	}
        
        public VideoControl getVideoControl() {
            return videoControl;
        }
        
	public void handleException(Exception e) {
		System.err.println(e);
	}
}
